package com.spring.sd.aware;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import javax.annotation.PostConstruct;


/**
 * 当同时实现 Aware 接口和 InitializingBean 接口时，会先执行 Aware 接口。
 *
 * BeanFactoryAware 、ApplicationContextAware 和 EmbeddedValueResolverAware
 * 三个接口的功能可以使用 @Autowired 注解实现，InitializingBean 接口的功能也可以使用 @PostConstruct 注解实现，为什么还要使用接口呢？
 *
 * @Autowired 和 @PostConstruct 注解的解析需要使用 Bean 后置处理器，属于拓展功能，而这些接口属于内置功能，
 * 不加任何拓展 Spring 就能识别。在某些情况下，拓展功能会失效，而内容功能不会失效。
 *
 * 再运行 main() 方法会发现使用的注解没有被成功解析，原因很简单，GenericApplicationContext 是一个干净的容器，
 * 其内部没有用于解析这些注解的后置处理器。如果想要这些注解生效，则需要添加必要的后置处理器
 * context.registerBean(AutowiredAnnotationBeanPostProcessor.class);
 * context.registerBean(CommonAnnotationBeanPostProcessor.class);
 *
 */
@Slf4j
public class MyBean implements BeanNameAware, ApplicationContextAware, InitializingBean {
    @Override
    public void setBeanName(String name) {
        log.info("当前 Bean: " + this + "名字叫: " + name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        log.info("当前 Bean: " + this + "容器是: " + applicationContext);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        log.info("当前 Bean: " + this + " 初始化");
    }


    @Autowired
    public void setApplicationContextWithAutowired(ApplicationContext applicationContext) {
        log.info("当前 Bean: " + this + " 使用 @Autowired 注解，容器是: " + applicationContext);
    }

    @PostConstruct
    public void init() {
        log.info("当前 Bean: " + this + " 使用 @PostConstruct 注解初始化");
    }

}